﻿using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Math.Geometry;
using System;
using AForge.Vision.Motion;

namespace Analizador_de_Semillas
{
    class Analizador
    {
        public static List<double[]> CargarHistograma(Bitmap picUno, Bitmap picDos)
        {
            List<double[]> series = new List<double[]>();

            try
            {
                ImageStatistics rgbStatisticsUno = new ImageStatistics(picUno);

                ImageStatistics rgbStatisticsDos = new ImageStatistics(picDos);

                double[] red = new double[256];

                for (int i = rgbStatisticsUno.Red.Min; i < rgbStatisticsUno.Red.Max; i++)
                {
                    red[i] = (rgbStatisticsUno.Red.Values[i] + rgbStatisticsDos.Red.Values[i]) / 2;
                }

                series.Add(red);

                double[] blue = new double[256];

                for (int i = rgbStatisticsUno.Blue.Min; i < rgbStatisticsUno.Blue.Max; i++)
                {
                    blue[i] = (rgbStatisticsUno.Blue.Values[i] + rgbStatisticsDos.Blue.Values[i]) / 2;
                }

                series.Add(blue);

                double[] green = new double[256];

                for (int i = rgbStatisticsUno.Green.Min; i < rgbStatisticsUno.Green.Max; i++)
                {
                    green[i] = (rgbStatisticsUno.Green.Values[i] + rgbStatisticsDos.Green.Values[i]) / 2;
                }

                series.Add(green);

                rgbStatisticsUno = null;

                rgbStatisticsDos = null;
            }
            catch (Exception)
            {
                
            }
            

            return series;
        }

        private static int[] SmoothHistogram(int[] originalValues)
        {
            int[] smoothedValues = new int[originalValues.Length];

            double[] mask = new double[] { 0.25, 0.5, 0.25 };

            for (int bin = 1; bin < originalValues.Length - 1; bin++)
            {
                double smoothedValue = 0;
                for (int i = 0; i < mask.Length; i++)
                {
                    smoothedValue += originalValues[bin - 1 + i] * mask[i];
                }
                smoothedValues[bin] = (int)smoothedValue;
            }

            return smoothedValues;
        }

        public static int[] StatisticsImage(PictureBox picUno, PictureBox picDos, string canal)
        {
            int[] values = new int[256];

            Bitmap imagenUno = new Bitmap(picUno.Image);

            Bitmap imagenDos = new Bitmap(picDos.Image);

            ImageStatistics rgbStatisticsUno = new ImageStatistics(imagenUno);

            ImageStatistics rgbStatisticsDos = new ImageStatistics(imagenDos);

            switch (canal)
            {
                case "Rojo":

                    for (int i = rgbStatisticsUno.Red.Min; i < rgbStatisticsUno.Red.Max; i++)
                    {
                        values[i] = (rgbStatisticsUno.Red.Values[i] + rgbStatisticsDos.Red.Values[i]) / 2;
                    }

                    break;

                case "Azul":

                    for (int i = rgbStatisticsUno.Blue.Min; i < rgbStatisticsUno.Blue.Max; i++)
                    {
                        values[i] = (rgbStatisticsUno.Blue.Values[i] + rgbStatisticsDos.Blue.Values[i]) / 2;
                    }

                    break;

                case "Verde":

                    for (int i = rgbStatisticsUno.Green.Min; i < rgbStatisticsUno.Green.Max; i++)
                    {
                        values[i] = (rgbStatisticsUno.Green.Values[i] + rgbStatisticsDos.Green.Values[i]) / 2;
                    }

                    break;
            }

            return values;
        }

        public static int ContarObjetos(PictureBox pic)
        {
            Bitmap img = new Bitmap(pic.Image);

            FiltersSequence seq = new FiltersSequence();
            seq.Add(Grayscale.CommonAlgorithms.BT709);  //First add  GrayScaling filter
            seq.Add(new OtsuThreshold()); //Then add binarization(thresholding) filter
            Bitmap temp = seq.Apply(img); // Apply filters on source image

            //BitmapData data = img.LockBits(
            //    new Rectangle(0, 0, img.Width, img.Height),
            //        ImageLockMode.ReadWrite, img.PixelFormat);

            //ColorFiltering colorFilter = new ColorFiltering();

            //colorFilter.Red = new IntRange(0, 64);
            //colorFilter.Green = new IntRange(0, 64);
            //colorFilter.Blue = new IntRange(0, 64);
            //colorFilter.FillOutsideRange = false;

            ////colorFilter.ApplyInPlace(data);

            // process image with blob counter
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight = 2;
            blobCounter.MinWidth = 2;

            blobCounter.ProcessImage(temp);
            Blob[] blobs = blobCounter.GetObjectsInformation();
            //img.UnlockBits(data);

            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();

            Graphics g = Graphics.FromImage(img);
            Pen redPen = new Pen(Color.Red, 2);

            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List<IntPoint> edgePoints =
                    blobCounter.GetBlobsEdgePoints(blobs[i]);

                AForge.Point center;
                float radius;

                if (shapeChecker.IsCircle(edgePoints, out center, out radius))
                {
                    g.DrawEllipse(redPen,
                        (float)(center.X - radius), (float)(center.Y - radius),
                        (float)(radius * 2), (float)(radius * 2));
                }
                else
                {
                    List<IntPoint> corners;

                    if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                    {
                        if (shapeChecker.CheckPolygonSubType(corners) ==
                            PolygonSubType.Rectangle)
                        {
                            g.DrawPolygon(redPen, ToPointsArray(corners));
                        }
                        else
                        {
                            g.DrawPolygon(redPen, ToPointsArray(corners));
                        }
                    }
                    else
                    {
                        corners = PointsCloud.FindQuadrilateralCorners(edgePoints);
                        g.DrawPolygon(redPen, ToPointsArray(corners));
                    }
                  }
                }

                redPen.Dispose();
                g.Dispose();

                pic.Image = img;

                return blobs.Length;
            }

        private static System.Drawing.Point[] ToPointsArray(List<IntPoint> points)
        {
            System.Drawing.Point[] array = new System.Drawing.Point[points.Count];

            for (int i = 0, n = points.Count; i < n; i++)
            {
                array[i] = new System.Drawing.Point(points[i].X, points[i].Y);
            }

            return array;
        }

        public static double[] GetPercentColor(Bitmap picUno, Bitmap picDos)
        {
            double[] p = new double[3];
            
            try
            {
                Color tempColor;
                double sumR = 0;
                double sumG = 0;
                double sumB = 0;
                double cantPix = 0;

                for (int i = 0; i < picUno.Height; i++)
                {
                    for (int j = 0; j < picUno.Width; j++)
                    {
                        tempColor = picUno.GetPixel(j, i);
                        sumR += Convert.ToInt32(tempColor.R);
                        sumG += Convert.ToInt32(tempColor.G);
                        sumB += Convert.ToInt32(tempColor.B);
                        cantPix++;
                    }
                }

                for (int i = 0; i < picDos.Height; i++)
                {
                    for (int j = 0; j < picDos.Width; j++)
                    {
                        tempColor = picDos.GetPixel(j, i);
                        sumR += Convert.ToInt32(tempColor.R);
                        sumG += Convert.ToInt32(tempColor.G);
                        sumB += Convert.ToInt32(tempColor.B);
                        cantPix++;
                    }
                }

                p[0] = Math.Round((sumR / cantPix / 255) * 100 , 2);

                p[1] = Math.Round((sumB / cantPix / 255) * 100 , 2);

                p[2] = Math.Round((sumG / cantPix / 255) * 100 , 2);
            }
            catch (Exception)
            {

            }

            return p;
        }

        public static double[] GetAvgSize(BlobCountingObjectsProcessing counterUno, BlobCountingObjectsProcessing counterDos)
        {
            double[] sizies = new double[3];
            double sumH = 0;
            double sumW = 0;
            double cant = 0;

            try
            {
                foreach (var item in counterUno.ObjectRectangles)
                {
                    sumH += item.Height;

                    sumW += item.Width;
                }

                foreach (var item in counterDos.ObjectRectangles)
                {
                    sumH += item.Height;

                    sumW += item.Width;
                }

                cant = counterUno.ObjectRectangles.Length + counterDos.ObjectRectangles.Length;

                sizies[0] = Math.Round(sumH / cant,2);

                sizies[1] = Math.Round(sumW / cant,2);

                sizies[2] = cant / 2;
                
            }
            catch (Exception)
            {
           
            }

            return sizies;
        }
    }
}
